#ifndef	SUDOKU_FIELD_H
#define	SUDOKU_FIELD_H

#include <set>
#include <unordered_set>
#include <vector>
#include <iostream>
#include <boost/foreach.hpp>

using namespace std;

template <typename T> class ValuesCmp;

//------------------------------------------------------------------------------------------------------------
class SudokuField
{
    public:
        SudokuField(int pid, vector<int>* pinitialAvailableValues);
        void initAvailableSet();
        virtual set<int,ValuesCmp<vector<int>* > >* getAvailableValues() = 0;// {return &availableValues;} // {return &availableValues;}
        int getId() const {return id;}
        void print() const;
        set<int>::iterator value;
    protected:
        vector<int>* initialAvailableValues;
        set<int, ValuesCmp<vector<int>* > >* availableValues;
        vector<int> ordering;
        int id;
};
//------------------------------------------------------------------------------------------------------------
class SudokuFieldOrder: public SudokuField
{
    public:
        SudokuFieldOrder(int id, vector<int>* pinitialAvailableValues);
        //void initAvailableSet();
        virtual set<int,ValuesCmp<vector<int>* > >* getAvailableValues() {return availableValues;};
        //int getId() const {return id;}
        //void print() const;
        //set<int>::iterator value;
    protected:
//        vector<int> initialAvailableValues;
		//set<int> availableValues;
        //int id;
};
//------------------------------------------------------------------------------------------------------------
template <typename T>
class ValuesCmp
{
private:
	T ordering;
public:
	ValuesCmp(T pordering): ordering(pordering) {}
	bool operator() (const int& lhs, const int& rhs) const {return (*ordering)[lhs] < (*ordering)[rhs];}
};
//------------------------------------------------------------------------------------------------------------
class SudokuFieldRandom :public SudokuField
{
    public:
        SudokuFieldRandom(int id, vector<int>* pinitialAvailableValues);
        //void initAvailableSet(); //copy values from initial set to available set
        virtual set<int,ValuesCmp<vector<int>* > >* getAvailableValues() {return availableValues;};
    private:
    	void randVector(vector<int>& v);
    	//void randomizeAvailableValues(vector<int>* src, vector<int>* dest);
		//vector<int> order;
        //int value;
        //SudokuRelations * relations;
};
//------------------------------------------------------------------------------------------------------------
#endif
